/*
 *   The contents of this file are subject to the Mozilla Public License
 *   Version 1.1 (the "License"); you may not use this file except in
 *   compliance with the License. You may obtain a copy of the License at
 *   http://www.mozilla.org/MPL/
 *
 *   Software distributed under the License is distributed on an "AS IS"
 *   basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
 *   License for the specific language governing rights and limitations
 *   under the License.
 *
 *   The Original Code is Matra - the DTD Parser.
 *
 *   The Initial Developer of the Original Code is Conrad S Roche.
 *   Portions created by Conrad S Roche are Copyright (C) Conrad 
 *   S Roche. All Rights Reserved.
 *
 *   Alternatively, the contents of this file may be used under the terms
 *   of the GNU GENERAL PUBLIC LICENSE Version 2 or any later version
 *   (the  "[GPL] License"), in which case the
 *   provisions of GPL License are applicable instead of those
 *   above.  If you wish to allow use of your version of this file only
 *   under the terms of the GPL License and not to allow others to use
 *   your version of this file under the MPL, indicate your decision by
 *   deleting  the provisions above and replace  them with the notice and
 *   other provisions required by the GPL License.  If you do not delete
 *   the provisions above, a recipient may use your version of this file
 *   under either the MPL or the GPL License."
 *
 *   [NOTE: The text of this Exhibit A may differ slightly from the text of
 *   the notices in the Source Code files of the Original Code. You should
 *   use the text of this Exhibit A rather than the text found in the
 *   Original Code Source Code for Your Modifications.]
 *
 * Created: Conrad S Roche <derupe at users.sourceforge.net>,  19-Oct-2003
 */
package com.conradroche.matra.parser;

import com.conradroche.dtd.decl.PI;
import com.conradroche.dtd.parser.PIReader;
import com.conradroche.matra.data.DTDData;
import com.conradroche.matra.data.ParseableData;
import com.conradroche.matra.exception.DTDSyntaxException;

/**
 * Class to read the comment text.
 *
 * @author Conrad Roche
 */
public class PIReaderImpl implements PIReader {

	/**
	 * Token identifying a PI.
	 */
	private static final char[] PI_START = "<?".toCharArray();
	
	/**
	 * PIReaderImpl Constructor.
	 */
	public PIReaderImpl() {
		super();
	}

	/**
	 * Read the processing instruction from the data stream.
	 * 
	 * @param data The stream from which to read the processing 
	 * 			instruction.
	 * 
	 * @return The processing instruction.
	 * 
	 * @throws DTDSyntaxException If the processing instruction 
	 * 			contains a syntax error. 
	 */
	public PI readPI(DTDData data) throws DTDSyntaxException {
		
		if(!isPIStart(data)) {
			return null; 
		}
	
		StringBuffer instr = new StringBuffer("");
	
		//read the '<?' PI beginning
		data.skipChars(PI_START.length);
		
		String piTarget = data.getNextName();
		
		if((piTarget == null || piTarget.length() == 0)) {
			
			if(ParseableData.isWhiteSpace(data.lookNextChar())) {
				throw new DTDSyntaxException("The Target should be specified for the PI immediately following the '<?'");
			} else {
				throw new DTDSyntaxException("The Target for the PI must be a 'Name'. Invalid char '" + 
						data.lookNextChar() + "' encountered in the target.");
			}
		}
		
		PI pi = new com.conradroche.matra.decl.PI();
		pi.setPITarget(piTarget);
		data.skipWhiteSpace();
		
		while( !data.endOfData() ) {
			
			if(data.lookNextChar() == '?' && data.peekAhead(2) == '>') { //end of PI
				
				data.skipChars(2); //'?>'
				
				pi.setInstructions(instr.toString());
				return pi;
			}
			
			instr.append(data.getNextChar());
		}
		
		//Got End of Data before reaching '?>'
		throw new DTDSyntaxException("Invalid PI block encountered at location " + 
					data.getCurrentLocation() + ".", data.getCurrentLocation());

	}

	/**
	 * Checks if there is a processing instruction at the 
	 * current location of the data.
	 * 
	 * @param data The data to be parsed.
	 * 
	 * @return <code>true</code> if the current location
	 * 		of the data has a processing instruction; 
	 * 		<code>false</code> otherwise.
	 */
	public boolean isPIStart(DTDData data) {
		
		if(data == null || data.endOfData()) {
			return false;
		}
		
		if(!data.nextStringEquals(PI_START)) {
			return false;
		}
		
		return true;
//		CR: NOTE: CHANGED THIS TEMPORARILY FROM FALSE TO TRUE!!!
		/*char ch = data.peekAhead(PI_START.length + 1); 
		if( ch != 'x' && ch != 'X') {
			return true;
		}
		
		ch = data.peekAhead(PI_START.length + 2); 
		if( ch != 'm' && ch != 'M') {
			return true;
		}
		
		ch = data.peekAhead(PI_START.length + 3); 
		if( ch != 'l' && ch != 'L') {
			return true;
		}
		
		//<?xml is a textdecl.
		return false;*/  
	}
}

